#pragma once
#include <iostream>
#include <cstdlib>
#include <unistd.h>
#include <cstring>
#include <string>
#include <signal.h>
#include <functional>
#include <strings.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <pthread.h>

#include "err.hpp"
#include "ThreadPool_V4.hpp"
#include "Task.hpp"
#include "log.hpp"
namespace tcp_server
{
    using func_t = std::function<std::string(std::string)>; // 业务处理函数--回调函数
    class TcpServer;
    class ThreadData
    {
    public:
        ThreadData(int fd, const std::string &ip, const uint16_t &port, TcpServer *ts) : sock(fd), clientip(ip), clientport(port), current(ts)
        {
        }
        ~ThreadData()
        {
        }

    public:
        int sock;
        std::string clientip;
        uint16_t clientport;
        TcpServer *current;
    };
    static const uint16_t defaultport = 8080;
    static const int backlog = 32;
    class TcpServer
    {
    public:
        TcpServer(func_t func, uint16_t port = defaultport) : func_(func), port_(port), quit_(true)
        {
        }
        void Initserver()
        {
            // 1.创建套接字，打开文件
            listensock_ = socket(AF_INET, SOCK_STREAM, 0); //
            if (listensock_ < 0)
            {
                // std::cerr << "socket create error:" << strerror(errno) << std::endl;
                logMessage(Fatal, "code:%d,socket create error:%s", errno, strerror(errno));
                exit(SOCKET_ERROR);
            }
            logMessage(Info, "code:%d,socket create success:%s", errno, strerror(errno));
            // 2.bind服务器
            /*int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);*/
            struct sockaddr_in local;
            memset(&local, 0, sizeof(local)); // memset初始化，紧接着变量后面
            local.sin_family = AF_INET;
            local.sin_port = htons(port_);
            local.sin_addr.s_addr = INADDR_ANY;
            if (bind(listensock_, (struct sockaddr *)&local, sizeof(local)) < 0)
            {
                // std::cerr << "bind error:" << strerror(errno) << std::endl;
                logMessage(Fatal, "code:%d,bind sock error:%s", errno, strerror(errno));
                exit(BIND_ERROR);
            }
            logMessage(Info, "code:%d,bind sock success:%s", errno, strerror(errno));
            // 3.监听listen--客户端与服务器先建立连接
            /* int listen(int sockfd, int backlog);*/
            if (listen(listensock_, backlog) < 0)
            {
                // std::cerr << "listen error:" << strerror(errno) << std::endl;
                logMessage(Fatal, "code:%d,listen sock error:%s", errno, strerror(errno));
                exit(LISTEN_ERROR);
            }
            logMessage(Info, "code:%d,listen sock success:%s", errno, strerror(errno));
        }
        void Start()
        {
            // signal(SIGCHLD,SIG_IGN);  //对阻塞信号进行忽略，所以父进程进行信号回收的时候，就不会进行阻塞式的等待。
            quit_ = false;
            while (!quit_)
            {
                struct sockaddr_in client;
                socklen_t len = sizeof(client);
                // 4.获取连接accept
                /* int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);*/
                int sock = accept(listensock_, (struct sockaddr *)&client, &len);
                if (sock < 0)
                {
                    // std::cerr << "accept error" << std::endl;
                    logMessage(Warning, "code:%d,accept error:%s", errno, strerror(errno));
                    continue;
                }
                // 5.获取新连接成功
                // std::cout << "获取新连接成功：" << sock << " from " << listensock_ << "->";
                std::string clientip = inet_ntoa(client.sin_addr);
                uint16_t clientport = ntohs(client.sin_port);
                std::string name = clientip + '-' + std::to_string(clientport);
                // std::cout << name << std::endl;
                logMessage(Info, "获取新连接成功：%d from %d -> %s", sock, listensock_, name.c_str());
                // 多进程版v2
                //  pid_t id = fork();
                //  if(id < 0)
                //  {
                //     close(sock);
                //     continue;
                //  }
                //  else if(id == 0)
                //  {//子进程
                //    close(listensock_);  //关闭不需要文件标识符--建议关闭
                //    if(fork() > 0) exit(0);
                //    server(sock,clientip,clientport); // 获取服务
                //    exit(0);
                //  }
                //  //父进程
                //  close(sock);  //关闭不需要文件标识符--必须关闭,不然会造成文件描述符资源越来越少
                //  pid_t ret = waitpid(id,nullptr,0);  //阻塞是等待
                //  if(ret == id) std::cout<<"wait child:"<<id<<"success"<<std::endl;

                // 多线程版本v3
                /*主线程获取套接字，子线程提供service服务*/
                // ThreadData *td = new ThreadData(sock,clientip,clientport,this);
                //     // 子线程调用service服务，service的参数：sock，ip，port-->用类封装传过去
                // pthread_create(&t, nullptr, ThreadRountine, td);

                // 线程池版本v4
                /*将任务交给线程池，让线程池去处理，线程池要处理什么样的任务：service*/
                Task t(sock, clientip, clientport, bind(&TcpServer::service, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
                ThreadPool<Task>::gitinstance()->pushTask(t); // 引用只能调用对象
            }
        }
        //   static void* ThreadRountine(void* args)
        //    {
        // pthread_detach(pthread_self()); // 主线程与子进程分离
        //        ThreadData* td = static_cast<ThreadData*> (args);
        //        td->current->service(td->sock,td->clientip,td->clientport);
        //        //服务退出,释放对象
        //        delete td;
        //        return nullptr;
        //    }
        void service(int sock, const std::string &clientip, const uint16_t &clientport)
        {
            std::string name = clientip + "-" + std::to_string(clientport);
            // v2
            //  从sock文件中读取数据--即从客户端读取数据
            char buffer[1024];
            ssize_t n = read(sock, buffer, sizeof(buffer) - 1);
            if (n > 0)
            {
                // std::cout << name << ">>>";
                buffer[n] = '\0';
                // std::cout << buffer << std::endl;
                logMessage(Debug, "%s>>>%s", name.c_str(), buffer);
                // 向sock文件写入数据--即将客户端的数据处理完之后发过去
                std::string sendmassage = func_(buffer);
                /* ssize_t write(int fd, const void *buf, size_t count);*/
                n = write(sock, sendmassage.c_str(), sendmassage.size());
            }
            else if (n == 0)
            { // 套接字关闭
              // std::cout << name << ">>>";
              // std::cout << "quit,me too!!" << std::endl;
                logMessage(Debug, "%s>>>quit,me too!!", name.c_str());
            }
            else
            {
                // std::cerr << "read error：" << strerror(errno) << std::endl;
                logMessage(Fatal, "code:%d read error：%s",errno,strerror(errno));
            }
            close(sock);
            // v1
            //  while (true)
            //  {
            //      // 从sock文件中读取数据--即从客户端读取数据
            //      /*ssize_t read(int fd, void *buf, size_t count);*/
            //      char buffer[1024];
            //      ssize_t n = read(sock, buffer, sizeof(buffer) - 1);
            //      if (n > 0)
            //      {
            //          std::cout << name << "》";
            //          buffer[n] = '\0';
            //          std::cout << buffer << std::endl;
            //          // 向sock文件写入数据--即将客户端的数据处理完之后发过去
            //          std::string sendmassage = func_(buffer);
            //          /* ssize_t write(int fd, const void *buf, size_t count);*/
            //          n = write(sock, sendmassage.c_str(), sendmassage.size());
            //      }
            //      else if (n == 0)
            //      { // 套接字关闭
            //          std::cout << name << "》";
            //          std::cout << "quit,me too!!" << std::endl;
            //          close(sock);
            //          break;
            //      }
            //      else
            //      {
            //          std::cerr << "read error：" << strerror(errno) << std::endl;
            //          close(sock);
            //          break;
            //      }
            //  }
        }
        ~TcpServer()
        {
        }

    private:
        int listensock_;
        uint16_t port_;
        bool quit_;
        func_t func_;
        pthread_t t;
    };
}